//
//  GenericsAndNullabilityTest.m
//  test_simple_project
//
//  Objective-C泛型和可空性注解测试实现
//

#import "GenericsAndNullabilityTest.h"

NS_ASSUME_NONNULL_BEGIN

#pragma mark - Generic Container Implementation

@implementation GenericContainer

- (instancetype)initWithCapacity:(NSUInteger)capacity {
    self = [super init];
    if (self) {
        _items = [[NSMutableArray alloc] initWithCapacity:capacity];
    }
    return self;
}

- (void)addItem:(id)item {
    if (item) {
        [self.items addObject:item];
        self.currentItem = item;
    }
}

- (void)addItems:(NSArray *)items {
    [self.items addObjectsFromArray:items];
    if (items.count > 0) {
        self.currentItem = items.lastObject;
    }
}

- (nullable id)itemAtIndex:(NSUInteger)index {
    if (index < self.items.count) {
        return self.items[index];
    }
    return nil;
}

- (void)removeItem:(id)item {
    [self.items removeObject:item];
    if ([self.currentItem isEqual:item]) {
        self.currentItem = self.items.lastObject;
    }
}

- (NSUInteger)count {
    return self.items.count;
}

- (NSArray *)allItems {
    return [self.items copy];
}

- (NSArray *)filteredItemsUsingBlock:(BOOL (^)(id item))block {
    NSMutableArray *filtered = [[NSMutableArray alloc] init];
    for (id item in self.items) {
        if (block(item)) {
            [filtered addObject:item];
        }
    }
    return [filtered copy];
}

- (void)enumerateItemsUsingBlock:(void (^)(id item, NSUInteger index, BOOL *stop))block {
    [self.items enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        block(obj, idx, stop);
    }];
}

@end

#pragma mark - Generic Key-Value Store Implementation

@implementation GenericKeyValueStore

- (instancetype)init {
    self = [super init];
    if (self) {
        _storage = [[NSMutableDictionary alloc] init];
    }
    return self;
}

- (void)setValue:(id)value forKey:(id)key {
    if (key && value) {
        self.storage[key] = value;
    }
}

- (nullable id)valueForKey:(id)key {
    return self.storage[key];
}

- (NSArray *)allKeys {
    return self.storage.allKeys;
}

- (NSArray *)allValues {
    return self.storage.allValues;
}

@end

#pragma mark - Nullability Test Class Implementation

@implementation NullabilityTestClass

- (instancetype)init {
    self = [super init];
    if (self) {
        // 初始化nonnull属性
        _requiredString = @"Default Required String";
        _requiredArray = @[@"item1", @"item2"];
        
        // nullable和null_unspecified属性可以为nil
        _optionalString = nil;
        _unspecifiedString = nil;
        _optionalArray = nil;
        _optionalDictionary = nil;
        _optionalBlock = nil;
        
        // nonnull块必须有值
        _requiredBlock = ^NSString *(NSString *input) {
            return [input uppercaseString];
        };
    }
    return self;
}

- (nullable NSString *)processOptionalString:(nullable NSString *)input {
    if (input) {
        return [NSString stringWithFormat:@"Processed: %@", input];
    }
    return nil; // 可以返回nil因为返回值是nullable
}

- (nonnull NSString *)processRequiredString:(nonnull NSString *)input {
    // input保证不为nil，返回值也必须不为nil
    return [NSString stringWithFormat:@"Required Processing: %@", input];
}

- (nullable NSArray<NSString *> *)filterStrings:(nonnull NSArray<NSString *> *)strings 
                                      withBlock:(nonnull BOOL (^)(NSString *string))filterBlock {
    if (strings.count == 0) {
        return nil; // 可以返回nil
    }
    
    NSMutableArray<NSString *> *filtered = [[NSMutableArray alloc] init];
    for (NSString *string in strings) {
        if (filterBlock(string)) {
            [filtered addObject:string];
        }
    }
    
    return filtered.count > 0 ? [filtered copy] : nil;
}

- (void)complexMethodWithRequired:(nonnull NSString *)required 
                         optional:(nullable NSString *)optional
                      unspecified:(null_unspecified NSString *)unspecified
                       completion:(nullable void (^)(NSString *result, NSError *error))completion {
    
    NSLog(@"Processing - Required: %@", required);
    
    if (optional) {
        NSLog(@"Optional provided: %@", optional);
    } else {
        NSLog(@"Optional is nil");
    }
    
    if (unspecified) {
        NSLog(@"Unspecified provided: %@", unspecified);
    }
    
    // 模拟处理
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSString *result = [NSString stringWithFormat:@"Result for: %@", required];
        if (completion) {
            completion(result, nil);
        }
    });
}

@end

#pragma mark - Generic Nullability Test Implementation

@implementation GenericNullabilityTest

- (instancetype)init {
    self = [super init];
    if (self) {
        _requiredItems = [[NSMutableArray alloc] init];
        _optionalItems = nil; // nullable，可以为nil
    }
    return self;
}

- (void)addOptionalItem:(nullable id)item {
    if (!self.optionalItems) {
        self.optionalItems = [[NSMutableArray alloc] init];
    }
    
    if (item) {
        [(NSMutableArray *)self.optionalItems addObject:item];
    }
}

- (void)addRequiredItem:(nonnull id)item {
    [self.requiredItems addObject:item];
}

- (nullable id)firstOptionalItem {
    return self.optionalItems.firstObject; // 可能返回nil
}

- (nonnull id)firstRequiredItemWithDefault:(nonnull id)defaultItem {
    id firstItem = self.requiredItems.firstObject;
    return firstItem ?: defaultItem; // 保证返回非nil值
}

@end

#pragma mark - Global Functions Implementation

NSString * _Nullable CreateOptionalString(NSString * _Nonnull input) {
    if (input.length > 0) {
        return [input uppercaseString];
    }
    return nil; // 可以返回nil
}

NSArray<NSString *> * _Nonnull CreateStringArray(NSUInteger count) {
    NSMutableArray<NSString *> *array = [[NSMutableArray alloc] initWithCapacity:count];
    for (NSUInteger i = 0; i < count; i++) {
        [array addObject:[NSString stringWithFormat:@"Item %lu", (unsigned long)i]];
    }
    return [array copy]; // 必须返回非nil值
}

void ProcessWithCompletion(NSString * _Nonnull input, CompletionBlock _Nonnull completion) {
    // 模拟异步处理
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 模拟处理时间
        [NSThread sleepForTimeInterval:0.1];
        
        // 调用completion block
        dispatch_async(dispatch_get_main_queue(), ^{
            completion(YES, nil);
        });
    });
}

NS_ASSUME_NONNULL_END

#pragma mark - Usage Examples and Tests

@implementation GenericContainer (TestingExtensions)

- (void)demonstrateGenericUsage {
    NSLog(@"=== Generic Container Demo ===");
    
    // 字符串类型的泛型容器
    GenericContainer<NSString *> *stringContainer = [[GenericContainer alloc] initWithCapacity:5];
    [stringContainer addItem:@"Hello"];
    [stringContainer addItem:@"World"];
    [stringContainer addItems:@[@"How", @"Are", @"You"]];
    
    NSLog(@"String container count: %lu", (unsigned long)stringContainer.count);
    NSLog(@"Current item: %@", stringContainer.currentItem);
    
    // 使用泛型方法
    NSArray<NSString *> *longStrings = [stringContainer filteredItemsUsingBlock:^BOOL(NSString *item) {
        return item.length > 3;
    }];
    NSLog(@"Long strings: %@", longStrings);
    
    // 数字类型的泛型容器
    GenericContainer<NSNumber *> *numberContainer = [[GenericContainer alloc] initWithCapacity:3];
    [numberContainer addItems:@[@1, @42, @99, @7]];
    
    NSArray<NSNumber *> *largeNumbers = [numberContainer filteredItemsUsingBlock:^BOOL(NSNumber *item) {
        return item.intValue > 10;
    }];
    NSLog(@"Large numbers: %@", largeNumbers);
}

@end

@implementation NullabilityTestClass (TestingExtensions)

- (void)demonstrateNullabilityUsage {
    NSLog(@"=== Nullability Demo ===");
    
    // 测试nullable属性
    self.optionalString = @"Optional Value";
    NSLog(@"Optional string: %@", self.optionalString);
    
    self.optionalString = nil;
    NSLog(@"Optional string after nil: %@", self.optionalString ?: @"(nil)");
    
    // 测试方法参数的可空性
    NSString *result1 = [self processOptionalString:@"Test"];
    NSString *result2 = [self processOptionalString:nil];
    
    NSLog(@"Process result 1: %@", result1 ?: @"(nil)");
    NSLog(@"Process result 2: %@", result2 ?: @"(nil)");
    
    // 测试数组过滤
    NSArray<NSString *> *testArray = @[@"apple", @"banana", @"cherry", @"date"];
    NSArray<NSString *> *filtered = [self filterStrings:testArray withBlock:^BOOL(NSString *string) {
        return string.length > 4;
    }];
    
    NSLog(@"Filtered array: %@", filtered ?: @"(nil)");
    
    // 测试复杂方法
    [self complexMethodWithRequired:@"Required Value"
                           optional:@"Optional Value"
                        unspecified:nil
                         completion:^(NSString *result, NSError *error) {
        NSLog(@"Completion result: %@", result);
    }];
}

@end